import logging
import queue
from pathlib import Path
from app.core.config import settings
import inspect

# 全局日志队列
log_queue = queue.Queue()


class QueueHandler(logging.Handler):
    """自定义 Handler，将日志发送到队列"""

    def __init__(self, queue):
        super().__init__()
        self.queue = queue

    def emit(self, record):
        log_entry = self.format(record)
        self.queue.put(log_entry)


class Logger:
    def __init__(
            self,
            file_name,
            logger_name=None,
            level=logging.INFO,
            formatter=None,
            use_queue=True,
    ):
        self.file_name = Path(file_name)
        self.level = level
        self.logger = logging.getLogger(logger_name)
        self.logger.setLevel(self.level)

        # 修改默认日志格式，包含文件名、函数名和行号
        self.formatter = formatter or logging.Formatter(
            "[%(asctime)s - %(caller_filename)s:%(caller_function)s:%(caller_lineno)d - %(levelname)s]: %(message)s"
        )

        # 防止重复添加 Handler
        if not self.logger.handlers:
            self._init_handlers(use_queue)

    def _init_handlers(self, use_queue):
        """初始化 Handler，确保只执行一次"""
        # 确保日志目录存在
        self.file_name.parent.mkdir(parents=True, exist_ok=True)

        # FileHandler（写入文件）
        file_handler = logging.FileHandler(self.file_name)
        file_handler.setFormatter(self.formatter)
        self.logger.addHandler(file_handler)

        # StreamHandler（控制台输出）
        stream_handler = logging.StreamHandler()
        stream_handler.setFormatter(self.formatter)
        self.logger.addHandler(stream_handler)

        # QueueHandler（日志队列，可选）
        if use_queue:
            queue_handler = QueueHandler(log_queue)
            queue_handler.setFormatter(self.formatter)
            self.logger.addHandler(queue_handler)

    def set_level(self, level):
        """动态调整日志级别"""
        self.logger.setLevel(level)
        for handler in self.logger.handlers:
            handler.setLevel(level)

    def _log(self, level, msg):
        # 获取调用者的文件名、函数名和行号
        caller_frame = inspect.currentframe().f_back.f_back
        filename = inspect.getframeinfo(caller_frame).filename
        function_name = caller_frame.f_code.co_name
        lineno = caller_frame.f_lineno

        # 特殊处理 <module>，改成更友好的名字
        if function_name == '<module>':
            function_name = 'main'  # 你也可以改成 'main' 或其它字符串

        # 使用 extra 参数传递文件名、函数名和行号
        self.logger.log(level, msg, extra={
            'caller_filename': Path(filename).name,
            'caller_function': function_name,
            'caller_lineno': lineno
        })

    def info(self, msg):
        self._log(logging.INFO, msg)

    def debug(self, msg):
        self._log(logging.DEBUG, msg)

    def warning(self, msg):
        self._log(logging.WARNING, msg)

    def error(self, msg):
        self._log(logging.ERROR, msg)

    def critical(self, msg):
        self._log(logging.CRITICAL, msg)


# 全局默认日志（直接使用原生日志）
log = Logger(settings.LOGS_DIR + "/app.log", logger_name="app")

db_log = Logger(settings.LOGS_DIR + "/db.log", logger_name="db")

